package com.sciyichen.tcpclientbytes

import android.util.Base64
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.alibaba.fastjson.JSONArray
import org.junit.Assert.*
import org.junit.Test
import org.junit.runner.RunWith
import java.io.File
import java.io.FileOutputStream
import java.nio.charset.StandardCharsets
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit

/**
 * Instrumented test, which will execute on an Android device.
 *
 * See [testing documentation](http://d.android.com/tools/testing).
 */
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
    @Test
    fun useAppContext() {
        // Context of the app under test.
        val appContext = InstrumentationRegistry.getInstrumentation().targetContext
        assertEquals("com.sciyichen.tcpclientbytes.test", appContext.packageName)
    }
//    @Test
//    fun tcpCli() {
//        val options: MutableMap<String, Any> = mutableMapOf()
//        options["ip"] = "60.10.207.222"
//        options["port"] = 9001
//        val ip: String = options["ip"] as String
//        val port: Int = options["port"] as Int
//        val packetOperations = TcpClientBytesPluginImpl()
////            val jsonstr = "{\"request\":\"QueryStatus\"}"
//        val jsonstr = "{\"request\": \"GetDistortionImage\", \"type\": \"PNG\"}"
//        val checksum: Int = packetOperations.crcCcitt(jsonstr.toByteArray(), 0)
//        val byteArray: ByteArray = packetOperations.buildPacketFromJson(jsonstr, checksum)
////            val base64String = Base64.getEncoder().encodeToString(byteArray)
//        val base64String: ByteArray = Base64.encode(byteArray, Base64.NO_WRAP)
//        val list: List<String> = packetOperations.tcpClientByte(ip, port, base64String, 1024*2000,6000)
//        println(base64String)
//        val byteArray2: ByteArray = packetOperations.tcpClientBytes(ip, port, base64String, 1024*2000,6000)
//        val list1: List<String> = packetOperations.getAJsonPacketFromSocket(byteArray2, 1024*2000)
//        println(base64String)
//    }
        @Test
        fun tcpCli() {

            val options: MutableMap<String, Any> = mutableMapOf()
//            options["ip"] = "60.10.207.222"
//            options["port"] = 9001
//
//            val ip: String = options["ip"] as String
//            val port: Int = options["port"] as Int
//            val ip = "192.168.1.228"
            val ip = "60.10.207.222"
            val port = 9001
            val packetOperations = TcpClientBytesPluginImpl()
            var strHex1= "7ee700000019e30bf93d7b2272657175657374223a225175657279537461747573227d";
            var bytes1= packetOperations.hexToBytes(strHex1);
            println(bytes1)
            val list11: List<String> = packetOperations.getAJsonPacketFromSocket(bytes1, 1024);
            val jsonArray = JSONArray(listOf<Any>(list11))
            val json = jsonArray.toString()
            println(json );

            val jsonstr = "{\"request\":\"QueryStatus\"}"
//            val jsonstr = "{\"request\":\"GetDistortionImage\",\"type\":\"PNG\"}"
            val checksum: Int = packetOperations.crcCcitt(jsonstr.toByteArray(), 0)
            val byteArray: ByteArray = packetOperations.buildPacketFromJson(jsonstr, checksum)
            val base64String = Base64.encodeToString(byteArray, Base64.DEFAULT);
//            val list: List<String> = packetOperations.tcpClientByte(ip, port, base64String, 1024,6000)

            println(base64String)
            val byteArray2: ByteArray = packetOperations.tcpClientBytes(ip, port, base64String, 1024,6000)
            var strHex = packetOperations.bytesToHex(byteArray2);
            println(strHex)
            var bytes= packetOperations.hexToBytes(strHex);
            println(bytes)
            val list1: List<String> = packetOperations.getAJsonPacketFromSocket(byteArray2, 1024)
            val base64String2 = Base64.encodeToString(byteArray2, Base64.DEFAULT);
            println(base64String2)
            val decodedBytes: ByteArray = Base64.decode(base64String2, Base64.DEFAULT)
            println(decodedBytes)

            val list2: List<String> = packetOperations.getAJsonPacketFromSocket(decodedBytes, 1024)
            println(base64String)
        }

    @Test
    @Throws(Exception::class)
    fun testTcpByteStreamCommunication() {
        val plugin = TcpClientBytesPluginImpl()
        val host = "192.168.1.228"
//        val host = "60.10.207.222"
        val port = 9001
        val timeout = 30000 // 延长超时时间到30秒
        val jsonstr = "{\"request\":\"QueryStatus\"}"
        // 构建请求数据包
//        val jsonstr = "{\"request\": \"GetDistortionImage\", \"type\": \"PNG\"}"
        val checksum = plugin.crcCcitt(jsonstr.toByteArray(), 0)
        val testBytes = plugin.buildPacketFromJson(jsonstr, checksum)

        // 连接到服务器
        val connectLatch = CountDownLatch(1)
        plugin.connect(
            host, port,20000,
            { result ->
                println("连接成功: $result")
                connectLatch.countDown()
            },
            { error ->
                println("连接失败: $error")
                connectLatch.countDown()
            }
        )

        // 等待连接完成
        assertTrue(connectLatch.await(10, TimeUnit.SECONDS))

        // 设置数据回调 - 合并处理逻辑
        val receiveLatch = CountDownLatch(1)
        val receivedData = arrayOfNulls<ByteArray>(1)

        plugin.setDataByteArrayCallback { data ->
            receivedData[0] = data
            println("接收到数据长度: ${data.size}")

            // 尝试解析数据包 - 根据协议判断是否接收完整
            val packets = plugin.getAJsonPacketFromSocket(data, data.size)
            if (packets.isNotEmpty()) {
                println("解析到数据包: ${packets[0]}")

                // 对于图像请求，判断是否包含结束标记或足够的数据长度
                if (data.size > 1024) { // 假设图像数据至少1KB
                    receiveLatch.countDown()
                }
            }
        }

        // 发送字节流数据
        val sendLatch = CountDownLatch(1)
//        plugin.sendBytes(
//            testBytes,
//            { result ->
//                println("发送成功: $result")
//                sendLatch.countDown()
//            },
//            { error ->
//                println("发送失败: $error")
//                sendLatch.countDown()
//            }
//        )
        //

        val base64String =Base64.encodeToString(testBytes, Base64.DEFAULT);
        plugin.sendBase64Str(
            base64String,
            { result ->
                println("发送成功: $result")
                sendLatch.countDown()
            },
            { error ->
                println("发送失败: $error")
                sendLatch.countDown()
            }
        )

        // 等待发送完成
        assertTrue(sendLatch.await(10, TimeUnit.SECONDS))
        // 等待接收响应 - 延长超时时间
        val received =receiveLatch.await(30, TimeUnit.SECONDS) // 等待接收完成


        // 验证测试结果
        assertTrue("接收超时", received)
        assertNotNull("未收到响应", receivedData[0])
        assertTrue("响应数据为空", receivedData[0]!!.size > 0)

        try {
            // 尝试解析为图像数据
            val responseBytes = receivedData[0]!!

            // 验证是否为PNG图像(PNG文件以89 50 4E 47开头)
            if (responseBytes.size >= 4 &&
                responseBytes[0] == 0x89.toByte() &&
                responseBytes[1] == 0x50.toByte() &&
                responseBytes[2] == 0x4E.toByte() &&
                responseBytes[3] == 0x47.toByte()) {

                println("接收到有效的PNG图像数据，大小: ${responseBytes.size} 字节")

                // 保存图像用于调试
                val outputFile = File("received_image.png")
                FileOutputStream(outputFile).use { fos ->
                    fos.write(responseBytes)
                }
                println("图像已保存到: ${outputFile.absolutePath}")
            } else {
                // 尝试作为JSON解析
                val responseText = String(responseBytes, StandardCharsets.UTF_8)
                println("解码后文本: $responseText")

                // 检查是否包含错误信息
                if (responseText.contains("error") || responseText.contains("失败")) {
                    fail("服务器返回错误: $responseText")
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
            fail("处理响应数据时出错: ${e.message}")
        } finally {
            // 关闭连接
            val closeLatch = CountDownLatch(1)
            plugin.close(
                { result ->
                    println("关闭成功: $result")
                    closeLatch.countDown()
                },
                { error ->
                    println("关闭失败: $error")
                    closeLatch.countDown()
                }
            )

            // 等待关闭完成
            assertTrue(closeLatch.await(10, TimeUnit.SECONDS))
        }
    }
    // 最小测试用例
    @Test
    fun testConnectionStayAlive() {
        val plugin = TcpClientBytesPluginImpl()

//        val host = "192.168.1.228"
        val host = "60.10.207.222"
        val port = 9001
        val timeout = 30000 // 延长超时时间到30秒

        // 构建请求数据包
        val jsonstr = "{\"request\": \"GetDistortionImage\", \"type\": \"PNG\"}"
        val checksum = plugin.crcCcitt(jsonstr.toByteArray(), 0)
        val testBytes = plugin.buildPacketFromJson(jsonstr, checksum)
//        plugin.connect( host, port,
//            { println("连接成功") },
//            { println("连接失败: $it") }
//        )
//        // 连接到服务器
        val connectLatch = CountDownLatch(1)
        plugin.connect(
            host, port,30000,
            { result ->
                println("连接成功: $result")
                connectLatch.countDown()
            },
            { error ->
                println("连接失败: $error")
                connectLatch.countDown()
            }
        )

        // 等待连接完成
        assertTrue(connectLatch.await(10, TimeUnit.SECONDS))
//
        // 设置数据回调 - 合并处理逻辑
        val receiveLatch = CountDownLatch(1)
        val receivedData = arrayOfNulls<ByteArray>(1)

        plugin.setDataByteArrayCallback { data ->
            receivedData[0] = data
            println("接收到数据长度: ${data.size}")
            // 尝试解析数据包 - 根据协议判断是否接收完整
            val packets = plugin.getAJsonPacketFromSocket(data, data.size)
            if (packets.isNotEmpty()) {
                println("解析到数据包: ${packets[0]}")

                // 对于图像请求，判断是否包含结束标记或足够的数据长度
                if (data.size > 1024) { // 假设图像数据至少1KB
                    receiveLatch.countDown()
                }
            }
        }

        plugin.setStringCallback({ data ->
            println("接收到数据长度: ${data}")
        })
//
        // 发送字节流数据
        val sendLatch = CountDownLatch(1)
        plugin.sendBytes(
            testBytes,
            { result ->
                println("发送成功: $result")
                sendLatch.countDown()
            },
            { error ->
                println("发送失败: $error")
                sendLatch.countDown()
            }
        )

        // 等待发送完成
        assertTrue(sendLatch.await(10, TimeUnit.SECONDS))
        // 等待10秒，观察接收线程是否保持运行
        Thread.sleep(20000)

        // 关闭连接
        val closeLatch = CountDownLatch(1)
        plugin.close(
            { result ->
                println("关闭成功: $result")
                closeLatch.countDown()
            },
            { error ->
                println("关闭失败: $error")
                closeLatch.countDown()
            }
        )
    }
    @Test
    fun testConnectionStayAliveBase64Str() {
        val plugin = TcpClientBytesPluginImpl()

        val host = "192.168.1.228"
        val port = 9002
        val timeout = 10000

        // 构建请求数据包
        val jsonstr = "{\"request\":\"QueryStatus\"}"
        val checksum = plugin.crcCcitt(jsonstr.toByteArray(), 0)
        val testBytes = plugin.buildPacketFromJson(jsonstr, checksum)
        val base64String =Base64.encodeToString(testBytes, Base64.DEFAULT);

        // 用于验证接收到的数据
        val receivedData = mutableListOf<String>()
        val dataReceivedLatch = CountDownLatch(1)

        // 设置数据回调
        plugin.setDataByteArrayBase64StrCallback { data ->
            println("接收到数据byte[] 转base64的字符串: ${data}")
            receivedData.add(data)
            dataReceivedLatch.countDown()
        }

        plugin.setStringCallback { data ->
            println("接收到数据字符串utf8: ${data}")
            receivedData.add(data)
            dataReceivedLatch.countDown()
        }

        // 连接到服务器
        val connectLatch = CountDownLatch(1)
        plugin.connect(
            host, port, timeout,
            { result ->
                println("连接成功: $result")
                connectLatch.countDown()
            },
            { error ->
                println("连接失败: $error")
                connectLatch.countDown()
            }
        )

        // 等待连接完成
        assertTrue(connectLatch.await(15, TimeUnit.SECONDS))
//        assertTrue(plugin.isConnected(), "连接应该处于活跃状态")

        // 发送数据
        val sendLatch = CountDownLatch(1)
        plugin.sendBase64Str(
            base64String,
            { result ->
                println("发送成功: $result")
                sendLatch.countDown()
            },
            { error ->
                println("发送失败: $error")
                sendLatch.countDown()
            }
        )

        // 等待发送完成
        assertTrue(sendLatch.await(10, TimeUnit.SECONDS))

        // 等待接收数据
//        assertTrue(dataReceivedLatch.await(10, TimeUnit.SECONDS), "应该接收到数据")
//        assertFalse(receivedData.isEmpty(), "应该接收到数据")

        // 发送第二个请求，验证连接保持活跃
        val secondSendLatch = CountDownLatch(1)
        plugin.sendBase64Str(
            base64String,
            { result ->
                println("第二次发送成功: $result")
                secondSendLatch.countDown()
            },
            { error ->
                println("第二次发送失败: $error")
                secondSendLatch.countDown()
            }
        )

        // 等待第二次发送完成
        assertTrue(secondSendLatch.await(10, TimeUnit.SECONDS))

        // 等待接收第二个响应
        Thread.sleep(50000)
//        assertTrue(receivedData.size >= 2, "应该接收到至少两个响应")

        // 关闭连接
        val closeLatch = CountDownLatch(1)
        plugin.close(
            { result ->
                println("关闭成功: $result")
                closeLatch.countDown()
            },
            { error ->
                println("关闭失败: $error")
                closeLatch.countDown()
            }
        )

        // 等待关闭完成
        assertTrue(closeLatch.await(10, TimeUnit.SECONDS))
//        assertFalse(plugin.isConnected(), "连接应该已关闭")
    }
}